<?php
/**
 * Auction:Opration.php
 * @author qqinxl
 * Sun Sep 30 08:23:21 GMT 2007
 * 
 * @category   Auction
 * @package  
 * @copyright  Copyright (c) qqinxl
 */

class File_Opration {
	/**
	 * 图片格式
	 * @var array
	 */
	protected $_imageFormat = array('gif','jpg','jpeg','png');
	/**
     * Singleton instance
     * @var File_Opration
     */
	protected static $_instance = null;

	/**
     * Constructor
     * @return void
     */
	private function __construct(){
	}
	/**
     * Singleton instance 
     * @return File_Opration
     */
	public static function getInstance(){
		if (null === self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	/**
	 * 获得某目录内所有文件。第二个参数表示文件格式。
	 * @param string $path
	 * @param array $fileFormat
	 * @throws Exception
	 * @return array
	*/
	public function getAllFiles($path,$fileFormat = null,$ereg = null) {
		try{
			$list = array();
			if (($hndl = @opendir($path)) === false) {
				return false;
			}
			while (($file=readdir($hndl)) !== false) {
				if ($file != '.' && $file != '..') 	{
					if(is_file($path.$file)){
						if(empty($fileFormat)){
							if(!empty($ereg)){
								if(ereg($ereg,$file)){
									$list[] = $file;
								}
							}else{
								$list[] = $file;
							}
						}else{
							if(!is_array($fileFormat)){
								$fileFormat = array($fileFormat);
							}
							$pathinfo = pathinfo($path.$file);
							if(in_array(strtolower($pathinfo['extension']), $fileFormat)){
								if(!empty($ereg)){	
									if(  strpos($file,$ereg) !== false){
										$list[] = $file;
									}
								}else{
									$list[] = $file;
								}
							}
						}
					}
				}
			}
			closedir($hndl);
			
		}catch(Exception $e){
			throw $e;
		}
		return $list;
	}
	/**
	 * 获得某目录内所有目录
	 * @param string $path
	 * @throws Exception
	 * @return array
	*/
	public function getAllDirs($path) {
		try{
			$path .= DIRECTORY_SEPARATOR;
			$list = array();
			if (($hndl = @opendir($path)) === false) {
				return false;
			}
			while (($file=readdir($hndl)) !== false) {
				if ($file != '.' && $file != '..') 	{
					if(@is_dir($path.$file)){
						$list[] = $file;
					}
				}
			}
			closedir($hndl);
			
		}catch(Exception $e){
			throw $e;
		}
		return $list;
	}
	/**
	 * 获得某目录内所有图片文件。
	 * @param string $path
	 * @throws Exception
	 * @return array
	*/
	public function getAllImages($path) {
		try{
			$files = $this->getAllFiles($path,$this->_imageFormat);
			
		}catch(Exception $e){
			throw $e;
		}
		return $files;
	}
	/**
	 * 根据扩张名判断文件是否是图片
	 * @param string $file
	 * @return bool
	*/
	public function isImage($file){
		$pathinfo = pathinfo($file);
		if(in_array(strtolower($pathinfo['extension']), $this->_imageFormat)){
			return true;
		}else{
			return false;
		}
	}
	/**
	 * 获得文件或者目录属性
	 * @param string $path 目录名或者文件名
	 * @return array array('name','location','type','size','access','modify','change','read','write')
	*/
	public function getFileInfo($path=".") {
		$path = realpath($path);
		if (!$path) return $this->error_occur(0x000A, __FUNCTION__);
		$result = array(
		"name" => substr($path, strrpos($path, DIRECTORY_SEPARATOR)+1),
		"location" => $path,
		"type" => is_file($path) ? 1 : (is_dir($path) ? 0 : -1),
		"size" => filesize($path),
		"access" => fileatime($path),
		"modify" => filemtime($path),
		"change" => filectime($path),
		"read" => is_readable($path),
		"write" => is_writeable($path)
		);
		clearstatcache();
		return $result;
	}

	/**
	 * 获得目录的所有文件或目录，并排序
	 * @param string $path
	 * @return array
	*/
	public function getFileList($path) {
		$f = $d = array();
		//获取所有文件
		foreach ($this->getAllFiles($path) as $name) {
			if (@is_dir($path.$name)) {
				$d[] = $name;
			} else if (@is_file($path.$name)) {
				$f[] = $name;
			}
		}
		natcasesort($d);
		natcasesort($f);
		return array_merge($d, $f);
	}
	/**
	 * 获得一目录大小 使用递归的方法
	 * @param string $dir 目录名
	 * @return int $totalsize
	*/
	public function getDirSize($dir) {
		if (!preg_match('#/$#', $dir)) {
			$dir .= '/';
		}
		$totalsize = 0;
		//调用文件列表
		foreach ($this->getFileList($dir) as $name) {
			$totalsize += (@is_dir($dir.$name) ? $this->dir_size("$dir$name/") : (int)@filesize($dir.$name));
		}
		return $totalsize;
	}
	/**
	 * 获得文件头名
	 * @param string $key
	 * @throws Exception
	 * @return string
	*/
	public function getFileMimi($key = null){
		$mimetypes = array(
		'ez'        => 'application/andrew-inset',
		'hqx'        => 'application/mac-binhex40',
		'cpt'        => 'application/mac-compactpro',
		'doc'        => 'application/msWord',
		'bin'        => 'application/octet-stream',
		'dms'        => 'application/octet-stream',
		'lha'        => 'application/octet-stream',
		'lzh'        => 'application/octet-stream',
		'exe'        => 'application/octet-stream',
		'class'        => 'application/octet-stream',
		'so'        => 'application/octet-stream',
		'dll'        => 'application/octet-stream',
		'oda'        => 'application/oda',
		'pdf'        => 'application/pdf',
		'ai'        => 'application/postscript',
		'eps'        => 'application/postscript',
		'ps'        => 'application/postscript',
		'smi'        => 'application/smil',
		'smil'        => 'application/smil',
		'mif'        => 'application/vnd.mif',
		'xls'        => 'application/vnd.ms-Excel',
		'ppt'        => 'application/vnd.ms-Powerpoint',
		'wbxml'        => 'application/vnd.wap.wbxml',
		'wmlc'        => 'application/vnd.wap.wmlc',
		'wmlsc'        => 'application/vnd.wap.wmlscriptc',
		'bcpio'        => 'application/x-bcpio',
		'vcd'        => 'application/x-cdlink',
		'pgn'        => 'application/x-chess-pgn',
		'cpio'        => 'application/x-cpio',
		'csh'        => 'application/x-csh',
		'dcr'        => 'application/x-Director',
		'dir'        => 'application/x-director',
		'dxr'        => 'application/x-director',
		'dvi'        => 'application/x-dvi',
		'spl'        => 'application/x-futuresplash',
		'gtar'        => 'application/x-gtar',
		'hdf'        => 'application/x-hdf',
		'js'        => 'application/x-javascript',
		'skp'        => 'application/x-koan',
		'skd'        => 'application/x-koan',
		'skt'        => 'application/x-koan',
		'skm'        => 'application/x-koan',
		'latex'        => 'application/x-latex',
		'nc'        => 'application/x-netcdf',
		'cdf'        => 'application/x-netcdf',
		'sh'        => 'application/x-sh',
		'shar'        => 'application/x-shar',
		'swf'        => 'application/x-shockwave-flash',
		'sit'        => 'application/x-stuffit',
		'sv4cpio'    => 'application/x-sv4cpio',
		'sv4crc'    => 'application/x-sv4crc',
		'tar'        => 'application/x-tar',
		'tcl'        => 'application/x-tcl',
		'tex'        => 'application/x-tex',
		'texinfo'    => 'application/x-texinfo',
		'texi'        => 'application/x-texinfo',
		't'            => 'application/x-troff',
		'tr'        => 'application/x-troff',
		'roff'        => 'application/x-troff',
		'man'        => 'application/x-troff-man',
		'me'        => 'application/x-troff-me',
		'ms'        => 'application/x-troff-ms',
		'ustar'        => 'application/x-ustar',
		'src'        => 'application/x-wais-source',
		'xhtml'        => 'application/xhtml+xml',
		'xht'        => 'application/xhtml+xml',
		'zip'        => 'application/zip',
		'au'        => 'audio/basic',
		'snd'        => 'audio/basic',
		'mid'        => 'audio/midi',
		'midi'        => 'audio/midi',
		'kar'        => 'audio/midi',
		'mpga'        => 'audio/mpeg',
		'mp2'        => 'audio/mpeg',
		'mp3'        => 'audio/mpeg',
		'aif'        => 'audio/x-aiff',
		'aiff'        => 'audio/x-aiff',
		'aifc'        => 'audio/x-aiff',
		'm3u'        => 'audio/x-mpegurl',
		'ram'        => 'audio/x-pn-realaudio',
		'rm'        => 'audio/x-pn-realaudio',
		'rpm'        => 'audio/x-pn-realaudio-plugin',
		'ra'        => 'audio/x-realaudio',
		'wav'        => 'audio/x-wav',
		'pdb'        => 'chemical/x-pdb',
		'xyz'        => 'chemical/x-xyz',
		'bmp'        => 'image/bmp',
		'gif'        => 'image/gif',
		'ief'        => 'image/ief',
		'jpeg'        => 'image/jpeg',
		'jpg'        => 'image/jpeg',
		'jpe'        => 'image/jpeg',
		'png'        => 'image/png',
		'tiff'        => 'image/tiff',
		'tif'        => 'image/tiff',
		'djvu'        => 'image/vnd.djvu',
		'djv'        => 'image/vnd.djvu',
		'wbmp'        => 'image/vnd.wap.wbmp',
		'ras'        => 'image/x-cmu-raster',
		'pnm'        => 'image/x-portable-anymap',
		'pbm'        => 'image/x-portable-bitmap',
		'pgm'        => 'image/x-portable-graymap',
		'ppm'        => 'image/x-portable-pixmap',
		'rgb'        => 'image/x-rgb',
		'xbm'        => 'image/x-xbitmap',
		'XPm'        => 'image/x-xpixmap',
		'xwd'        => 'image/x-xwindowdump',
		'igs'        => 'model/iges',
		'iges'        => 'model/iges',
		'msh'        => 'model/mesh',
		'mesh'        => 'model/mesh',
		'silo'        => 'model/mesh',
		'wrl'        => 'model/vrml',
		'vrml'        => 'model/vrml',
		'Css'        => 'text/css',
		'html'        => 'text/html',
		'htm'        => 'text/html',
		'asc'        => 'text/plain',
		'txt'        => 'text/plain',
		'rtx'        => 'text/richtext',
		'rtf'        => 'text/rtf',
		'sgml'        => 'text/sgml',
		'sgm'        => 'text/sgml',
		'tsv'        => 'text/tab-separated-values',
		'wml'        => 'text/vnd.wap.wml',
		'wmls'        => 'text/vnd.wap.wmlscript',
		'etx'        => 'text/x-setext',
		'xsl'        => 'text/xml',
		'xml'        => 'text/xml',
		'mpeg'        => 'video/mpeg',
		'mpg'        => 'video/mpeg',
		'mpe'        => 'video/mpeg',
		'qt'        => 'video/quicktime',
		'mov'        => 'video/quicktime',
		//'3gp'        => 'video/quicktime',
		//'3g2'        => 'video/quicktime',
		'mxu'        => 'video/vnd.mpegurl',
		'avi'        => 'video/x-msvideo',
		'movie'        => 'video/x-sgi-movie',
		'ice'        => 'x-conference/x-cooltalk',
		);
		if(empty($key)){
			return $mimetypes;
		}else{
			if(isset($mimetypes[$key])){
				return $mimetypes[$key];
			}else{
				return null;
			}
		}
	}
	/**
 * 创建一个目录树
 *
 * 用法：
 * <code>
 * mkdirs('/top/second/3rd');
 * </code>
 *
 * @param string $dir
 * @param int $mode
 */
	public function mkdirs($dir, $mode = 0777){
		if (!is_dir($dir)) {
			mkdirs(dirname($dir), $mode);
			return mkdir($dir, $mode);
		}
		return true;
	}

	/**
 * 删除指定目录及其下的所有文件和子目录
 *
 * 用法：
 * <code>
 * // 删除 my_dir 目录及其下的所有文件和子目录
 * rmdirs('/path/to/my_dir');
 * </code>
 *
 * 注意：使用该函数要非常非常小心，避免意外删除重要文件。
 *
 * @param string $dir
 */
	public function rmdirs($dir){
		$dir = realpath($dir);
		if ($dir == '' || $dir == '/' ||
		(strlen($dir) == 3 && substr($dir, 1) == ':\\')){
			// 禁止删除根目录
			return false;
		}

		// 遍历目录，删除所有文件和子目录
		if(false !== ($dh = opendir($dir))) {
			while(false !== ($file = readdir($dh))) {
				if($file == '.' || $file == '..') { continue; }
				$path = $dir . DIRECTORY_SEPARATOR . $file;
				if (is_dir($path)) {
					if (!rmdirs($path)) { return false; }
				} else {
					unlink($path);
				}
			}
			closedir($dh);
			rmdir($dir);
			return true;
		} else {
			return false;
		}
	}
	/**
     * 向浏览器发送文件内容
     *
     * @param string $serverPath 文件在服务器上的路径（绝对或者相对路径）
     * @param string $filename 发送给浏览器的文件名（尽可能不要使用中文）
     * @param string $mimeType 指示文件类型
     */
	function sendFile($serverPath, $filename, $charset,$mimeType = 'application/octet-stream'){
		header("Content-Type: {$mimeType}");
		$filename = '"' . htmlspecialchars($filename) . '"';
		$filesize = filesize($serverPath);
		header("Content-Disposition: attachment; filename={$filename}; charset={$charset}");
		header('Pragma: cache');
		header('Cache-Control: public, must-revalidate, max-age=0');
		header("Content-Length: {$filesize}");
		readfile($serverPath);
		exit;
	}
	/**
* 发送文件 
* 
* @author: legend(legendsky@hotmail.com) 
* @link: http://www.ugia.cn/?p=109 
* @description: send file to client 
* @version: 1.0 
* 
* @param string   $fileName      文件名称或路径 
* @param string   $fancyName     自定义的文件名,为空则使用filename 
* @param boolean  $forceDownload 是否强制下载 
* @param integer  $speedLimit    速度限制,单位为字节,0为不限制,不支持windows服务器 
* @param string   $$contentType  文件类型,默认为application/octet-stream 
* 
* @return boolean 
*/ 
	function sendFile2($fileName, $fancyName = '', $forceDownload = true, $speedLimit = 0, $contentType = ''){
		if (!is_readable($fileName)){
			header("HTTP/1.1 404 Not Found");
			return false;
		}
		$fileStat = stat($fileName);
		$lastModified = $fileStat['mtime'];
		$md5 = md5($fileStat['mtime'] .'='. $fileStat['ino'] .'='. $fileStat['size']);
		$etag = '"' . $md5 . '-' . crc32($md5) . '"';
		header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT');
		header("ETag: $etag");
		if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified)	{
			header("HTTP/1.1 304 Not Modified");
			return true;
		}
		if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) < $lastModified)	{
			header("HTTP/1.1 304 Not Modified");
			return true;
		}
		if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&  $_SERVER['HTTP_IF_NONE_MATCH'] == $etag){
			header("HTTP/1.1 304 Not Modified");
			return true;
		}

		if ($fancyName == '')	{
			$fancyName = basename($fileName);
		}
		if ($contentType == '')	{
			$contentType = 'application/octet-stream';
		}
		$fileSize = $fileStat['size'];
		//$contentLength = $fileSize;
		//$isPartial = false;
		$matches = array();
		if (isset($_SERVER['HTTP_RANGE']))	{
			if (preg_match('/^bytes=(\d*)-(\d*)$/', $_SERVER['HTTP_RANGE'], $matches)){
				$startPos = $matches[1];
				$endPos = $matches[2];
				if ($startPos == '' && $endPos == ''){
					return false;
				}
				if ($startPos == ''){
					$startPos = $fileSize - $endPos;
					$endPos = $fileSize - 1;
				}else if ($endPos == ''){
					$endPos = $fileSize - 1;
				}
				$startPos = $startPos < 0 ? 0 : $startPos;
				$endPos = $endPos > $fileSize - 1 ? $fileSize - 1 : $endPos;
				$length = $endPos - $startPos + 1;
				if ($length < 0){
					return false;
				}
				$contentLength = $length;
				$isPartial = true;
			}
		}
		// send headers
		if ($isPartial){
			header('HTTP/1.1 206 Partial Content');
			header("Content-Range: bytes $startPos-$endPos/$fileSize");
		}else{
			header("HTTP/1.1 200 OK");
			$startPos = 0;
			$endPos = $contentLength - 1;
		}
		header('Pragma: cache');
		header('Cache-Control: public, must-revalidate, max-age=0');
		header('Accept-Ranges: bytes');
		header('Content-type: ' . $contentType);
		header('Content-Length: ' . $contentLength);
		if ($forceDownload){
			header('Content-Disposition: attachment; filename="' . rawurlencode($fancyName). '"');
		}
		header("Content-Transfer-Encoding: binary");
		$bufferSize = 2048;
		if ($speedLimit != 0){
			$packetTime = floor($bufferSize * 1000000 / $speedLimit);
		}
		$bytesSent = 0;
		$fp = fopen($fileName, "rb");
		fseek($fp, $startPos);
		//fpassthru($fp);
		while ($bytesSent < $contentLength && !feof($fp) && connection_status() == 0 ){
			if ($speedLimit != 0){
				list($usec, $sec) = explode(" ", microtime());
				$outputTimeStart = ((float)$usec + (float)$sec);
			}
			$readBufferSize = $contentLength - $bytesSent < $bufferSize ? $contentLength - $bytesSent : $bufferSize;
			$buffer = fread($fp, $readBufferSize);
			echo $buffer;
			ob_flush();
			flush();
			$bytesSent += $readBufferSize;
			if ($speedLimit != 0)	{
				list($usec, $sec) = explode(" ", microtime());
				$outputTimeEnd = ((float)$usec + (float)$sec);

				$useTime = ((float) $outputTimeEnd - (float) $outputTimeStart) * 1000000;
				$sleepTime = round($packetTime - $useTime);
				if ($sleepTime > 0)	{
					usleep($sleepTime);
				}
			}
		}
		return true;
	}

}